/////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2011 Eric Bowen
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 
// associated documentation files (the "Software"), to deal in the Software without restriction, including 
// without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
// copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 
// following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial 
// portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 
// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/////////////////////////////////////////////////////////////////////////////////////////////////////
// Author's blog: http://blog.scrappydog.com
// Updated source code available:  http://scrappydb.codeplex.com
/////////////////////////////////////////////////////////////////////////////////////////////////////

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Web.Caching;
using Amazon.SimpleDB;
using Amazon.SimpleDB.Model;
using ScrappyDB.BaseClasses;

namespace ScrappyDB
{
    public interface IDb : IDisposable
    {
        Cache WebCache { get; set; }

        SdbCollection<T> Query<T>() where T : class, new();

        SdbCollection<T> Query<T>(string query) where T : class, new();

        SdbCollection<T> Query<T>(string query, params object[] args) where T : class, new();

        SdbCollection<T> Query<T>(string query, string nextToken) where T : class, new();

        SdbCollection<T> Query<T>(string query, string nextToken, params object[] args)
            where T : class, new();

        SdbCollection<T> Query<T>(string query, string nextToken, int startPosition, int rowsToReturn) where T : class, new();

        SdbCollection<T> Query<T>(string query, string nextToken, int startPosition, int rowsToReturn,
                                        params object[] args) where T : class, new();

        SdbCollection<T> Query<T>(bool consistentRead) where T : class, new();

        SdbCollection<T> Query<T>(string query, bool consistentRead) where T : class, new();

        SdbCollection<T> Query<T>(string query, bool consistentRead, params object[] args)
            where T : class, new();

        SdbCollection<T> Query<T>(string query, string nextToken, bool consistentRead) where T : class, new();

        SdbCollection<T> Query<T>(string query, string nextToken, bool consistentRead, params object[] args)
            where T : class, new();

        /// <summary>
        /// Main SELECT Query method.  Returns collections of SimpleDbEntities.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="query"></param>
        /// <param name="nextToken"></param>
        /// <param name="startPosition"></param>
        /// <param name="rowsToReturn"></param>
        /// <param name="consistentRead"></param>
        /// <returns></returns>
        SdbCollection<T> Query<T>(string query, string nextToken, int startPosition, int rowsToReturn, bool consistentRead) where T : class, new();

        /// <summary>
        /// The query provided is expected to return a single value
        /// 
        /// Note: ConsistentRead defaults to TRUE because this method returns a single value
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        string QueryValue(string query);

        /// <summary>
        /// The query provided is expected to return a single value
        /// </summary>
        /// <param name="query">A complete SimpleDB select statement</param>
        /// <param name="consistentRead"></param>
        /// <returns></returns>
        string QueryValue(string query, bool consistentRead);

        Collection<T> QueryByExample<T>(T o) where T : class, new();

        T Find<T>(object id) where T : class, new();
        //T Find<T>(Guid id) where T : class, new();
        //T Find<T>(DateTime id) where T : class, new();
        //T Find<T>(int id) where T : class, new();
        //T Find<T>(string id) where T : class, new();

        T Find<T>(object id, bool consistentRead) where T : class, new();
        ///// <summary>
        ///// Returns 1 record based on the supplied Id (ItemName) value
        ///// </summary>
        ///// <typeparam name="T"></typeparam>
        ///// <param name="id">Guid</param>
        ///// <param name="consistentRead"></param>
        ///// <returns></returns>
        //T Find<T>(Guid id, bool consistentRead) where T : class, new();

        ///// <summary>
        ///// Returns 1 record based on the supplied Id (ItemName) value
        ///// </summary>
        ///// <typeparam name="T"></typeparam>
        ///// <param name="id">DateTime</param>
        ///// <param name="consistentRead"></param>
        ///// <returns></returns>
        //T Find<T>(DateTime id, bool consistentRead) where T : class, new();

        ///// <summary>
        ///// Returns 1 record based on the supplied Id (ItemName) value
        ///// </summary>
        ///// <typeparam name="T"></typeparam>
        ///// <param name="id"></param>
        ///// <param name="consistentRead"></param>
        ///// <returns></returns>
        //T Find<T>(int id, bool consistentRead) where T : class, new();

        ///// <summary>
        ///// Returns 1 record based on the supplied Id (ItemName) value
        ///// </summary>
        ///// <typeparam name="T"></typeparam>
        ///// <param name="id"></param>
        ///// <param name="consistentRead"></param>
        ///// <returns></returns>
        //T Find<T>(string id, bool consistentRead) where T : class, new();

        /// <summary>
        /// Returns a collection of ScrappyDbEntities based on a collection of Id's
        /// 
        /// Note: ConsistentRead defaults to FALSE because this method returns multiple values
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="id"></param>
        /// <returns></returns>
        SdbCollection<T> Find<T>(params object[] id) where T : class, new();

        /// <summary>
        /// Returns a collection of records based on the supplied List of Id's (ItemName's) value
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="id"></param>
        /// <param name="consistentRead"></param>
        /// <returns></returns>
        SdbCollection<T> Find<T>(bool consistentRead, params object[] id) where T : class, new();

        int Count<T>() where T : class, new();
        int Count<T>(string query) where T : class, new();
        int Count<T>(string query, string nextToken) where T : class, new();
        int Count<T>(string query, string nextToken, int startPosition, int rowsToReturn) where T : class, new();
        int Count<T>(bool consistentRead) where T : class, new();
        int Count<T>(string query, bool consistentRead) where T : class, new();
        int Count<T>(string query, string nextToken, bool consistentRead) where T : class, new();
        int Count<T>(string query, string nextToken, int startPosition, int rowsToReturn, bool consistentRead) where T : class, new();
        Collection<T> CountByExample<T>(T o) where T : class, new();
        void SaveChanges<T>(T o) where T : class, new();
        BatchPutAttributesRequest CreateBatchRequest<T>(T entity) where T : class, new();
        //BatchPutAttributesRequest CreateBatchRequest(string domainName);
        ReplaceableItem CreateBatchRequestItem<T>(T entity) where T : class, new();

        void BatchPut(BatchPutAttributesRequest batchRequest);

        void Delete<T>(T entity) where T : class, new();
        void Delete<T>(IEnumerable<T> entities) where T : class, new();
        void Delete<T>(params object[] ids) where T : class, new();

        T DeleteOrphanProperties<T>(Guid id) where T : class, new();
        T DeleteOrphanProperties<T>(string id) where T : class, new();
        AmazonSimpleDB Service { get; set; }
        string EntityCacheKey(string domainName, string id);
    }
}